﻿CREATE FUNCTION [QIC].[InterfaceFactory_V] (@ConfigName VARCHAR(50), @InterfaceId INT)
RETURNS NVARCHAR(MAX)
AS
BEGIN
 
	DECLARE @Retval VARCHAR(MAX)
	DECLARE @ObjectName VARCHAR(MAX)
	DECLARE @HasDelegateName BIT
	DECLARE @Implementation VARCHAR(MAX)
	DECLARE @TriggerName varchar(200)
	DECLARE @TriggerAction varchar(10)
	DECLARE @Declare VARCHAR(MAX)
	DECLARE @DelegateImplementation VARCHAR(MAX)
	DECLARE @NonDefaultDelegates VARCHAR(MAX)
	DECLARE @DelegateName VARCHAR(50)
	DECLARE @TriggerObjectName VARCHAR(200)
	DECLARE @SchemaName VARCHAR(50)

	SELECT @SchemaName = SCHEMA_NAME(schema_id) FROM sys.objects WHERE object_id = @InterfaceId

	DECLARE @Triggers TABLE (Action VARCHAR(10), Name VARCHAR(100))
 
	DECLARE @Delegate TABLE (DelegateId INT, InterfaceId INT, DelegateName VARCHAR(50), InterfaceType VARCHAR(50), TokenMap VARCHAR(50), CallFactory VARCHAR(50))
	DECLARE @Aspect TABLE (AspectId INT, InterfaceId INT, DelegateName VARCHAR(50), ActionName VARCHAR(50), AspectReturnToken VARCHAR(50), SortOrder INT, AspectType VARCHAR(50), TokenMap VARCHAR(50), CallFactory VARCHAR(50))
	DECLARE @Token QIC.TokenTable
	DECLARE @Call TABLE (Id INT IDENTITY(1,1), DelegateName VARCHAR(50), Call VARCHAR(MAX), ActionName varchar(50))

	INSERT INTO @Aspect (InterfaceId,AspectId,DelegateName,ActionName,AspectReturnToken,SortOrder,AspectType, TokenMap, CallFactory)
	SELECT InterfaceId,AspectId,DelegateName, ActionName, AspectReturnToken,SortOrder,AspectType,TokenMap, CallFactory
	FROM QIC.Aspect_(@ConfigName) aspect
	WHERE InterfaceId = @InterfaceId
	AND aspect.DelegateName = ''
 
	INSERT INTO @Delegate (InterfaceId,DelegateId,DelegateName,InterfaceType,TokenMap, CallFactory)
	SELECT InterfaceId,DelegateId, DelegateName, InterfaceType, TokenMap, CallFactory
	FROM QIC.Delegate_(@ConfigName) delegate
	WHERE InterfaceId = @InterfaceId
 
	INSERT INTO @Token (ObjectId, PropertyId, PropertyName, UserTypeId, Precision, Scale, MaxLength, IsOutPut, IsReadOnly)
	SELECT columns.object_id, columns.column_id, columns.name, columns.user_type_id, columns.precision, columns.scale, columns.max_length, 0, 0
	FROM sys.columns columns
	WHERE columns.object_id = @InterfaceId
	ORDER BY columns.column_id
 
	IF EXISTS (select * from @Token where PropertyName = 'DelegateName') 
	BEGIN
		SET @HasDelegateName = 1
	END
	ELSE
	BEGIN
		SET @HasDelegateName = 0
	END
 
	INSERT INTO @Token (ObjectId, PropertyId, PropertyName, UserTypeId, Precision, Scale, MaxLength, IsOutPut, IsReadOnly)
	SELECT distinct columns.object_id, columns.column_id, columns.name, columns.user_type_id, columns.precision, columns.scale, columns.max_length, 0, 0
	FROM sys.columns columns
	INNER JOIN @Delegate delegate
		ON delegate.DelegateId = columns.object_id
 
	INSERT INTO @Token (ObjectId, PropertyId, PropertyName, UserTypeId, Precision, Scale, MaxLength, IsOutPut, IsReadOnly)
	SELECT distinct parameters.object_id, parameters.parameter_id, parameters.name, parameters.user_type_id , parameters.precision, parameters.scale, parameters.max_length, parameters.is_output, parameters.is_readonly
	FROM sys.parameters parameters
	INNER JOIN @Aspect aspect
		ON aspect.AspectId = parameters.object_id
	WHERE parameters.parameter_id > 0
 
	INSERT INTO @Token (ObjectId, PropertyId, PropertyName, UserTypeId, Precision, Scale, MaxLength, IsOutPut, IsReadOnly)
	SELECT distinct aspect.AspectId, returntoken.PropertyId, aspect.AspectReturnToken, returntoken.UserTypeId, returntoken.Precision, returntoken.Scale, returntoken.MaxLength, returntoken.IsOutPut, returntoken.IsReadOnly
	FROM @Aspect aspect
	CROSS APPLY QIC.ObjectReturnToken(AspectId) returntoken
 
	SELECT @ObjectName = QIC.ObjectName(@InterfaceId)

	SET @Implementation = ''
	SELECT @Implementation += 
		QIC.CallFactory(@ConfigName,@Token, @InterfaceId, @InterfaceId,'','', 1, '', 'V') + ' WHERE 1=0' +
		QIC.LB() + QIC.Indent(1) + 'UNION ALL' + QIC.LB() 
 
	SELECT @Implementation += 
		QIC.CallFactory(@ConfigName,@Token,delegate.InterfaceId, delegate.DelegateId,'',delegate.TokenMap, 1, delegate.DelegateName, delegate.CallFactory) +
		QIC.LB() + QIC.Indent(1) + 'UNION ALL' + QIC.LB() 
	FROM @Delegate delegate
	WHERE @HasDelegateName = 1 OR delegate.DelegateName = 'DEFAULT'
 
	IF @Implementation <> '' SET @Implementation = LEFT(@Implementation,DATALENGTH(@Implementation) - 11)
 
	SET @NonDefaultDelegates = ''
	IF @HasDelegateName = 1
	BEGIN
		SELECT @NonDefaultDelegates += QUOTENAME(DelegateName,'''') + ',' from @Delegate delegate where DelegateName <> 'DEFAULT'
		IF @NonDefaultDelegates <> '' SET @NonDefaultDelegates = LEFT(@NonDefaultDelegates,DATALENGTH(@NonDefaultDelegates) - 1)
	END
 
	SET @Retval = 'ALTER VIEW ' + @ObjectName + QIC.LB()
	SET @Retval += 'AS' + QIC.LB()
	SET @Retval += ISNULL(@Implementation + QIC.LB(),'')		
	SET @Retval += 'GO' + QIC.LB()
 
	SET @TriggerName = UPPER(REPLACE(REPLACE(REPLACE(@ObjectName,']',''),'[',''),'.','_'))
 
	INSERT INTO @Triggers (Action,Name) VALUES 
	('INSERT', 'QIC_INSERT_' + @TriggerName),
	('DELETE', 'QIC_DELETE_' + @TriggerName),
	('UPDATE', 'QIC_UPDATE_' + @TriggerName)
 
	DECLARE triggerCursor CURSOR LOCAL FOR
	SELECT Name FROM @Triggers
 
	OPEN triggerCursor
 
	WHILE (1=1)
	BEGIN
		FETCH NEXT FROM triggerCursor INTO @TriggerName
		IF @@FETCH_STATUS <> 0 BREAK
		SET @TriggerObjectName = QUOTENAME(@SchemaName) + '.' + QUOTENAME(@TriggerName)
		SET @Retval += 'IF OBJECT_ID(''' + @TriggerObjectName + ''') IS NOT NULL DROP TRIGGER ' + @TriggerObjectName + QIC.LB()
	END
 
	CLOSE triggerCursor
	DEALLOCATE triggerCursor
 
	-- RENDER TRIGGERS
	BEGIN
 
		DECLARE triggerCursor CURSOR LOCAL FAST_FORWARD FOR
		SELECT Name,Action FROM @Triggers
 
		OPEN triggerCursor
 
		WHILE (1=1)
		BEGIN
			FETCH NEXT FROM triggerCursor INTO @TriggerName, @TriggerAction
			IF @@FETCH_STATUS <> 0 BREAK
 
			SET @Implementation = ''
			SET @DelegateImplementation = ''
			SET @Declare = ''
 
			SELECT @Declare = QIC.TokenDeclare(@Token,@InterfaceId, 1)
 
			DELETE @Call
 
			INSERT INTO @Call (DelegateName,Call,ActionName)
			SELECT aspect.DelegateName, QIC.CallFactory(@ConfigName, @Token, @InterfaceId, aspect.AspectId, aspect.AspectReturnToken, aspect.TokenMap, CASE WHEN aspect.DelegateName IN ('DEFAULT','') OR @HasDelegateName = 0 THEN 1 ELSE 2 END, '', aspect.CallFactory), aspect.ActionName
			FROM @Aspect aspect
			WHERE aspect.ActionName IN ('BEFORE','BEFORE ' + @TriggerAction)
			ORDER BY aspect.SortOrder	
 
			INSERT INTO @Call (DelegateName,Call,ActionName)
			SELECT delegate.DelegateName, QIC.CallFactory(@ConfigName,@Token,delegate.InterfaceId, delegate.DelegateId,'',delegate.TokenMap, 1, delegate.delegatename, delegate.CallFactory + @TriggerAction) + 
					CASE @HasDelegateName 
						WHEN 1 THEN 
							CASE @TriggerAction WHEN 'INSERT' THEN ' WHERE ' ELSE ' AND ' END +
							CASE @TriggerAction WHEN 'DELETE' THEN 'deleted.' ELSE 'inserted.' END +
							CASE delegate.DelegateName WHEN 'DEFAULT' 
								THEN 'DelegateName NOT IN (' + @NonDefaultDelegates + ')'
								ELSE 'DelegateName = ' + QUOTENAME(delegate.delegatename,'''')
							END
						ELSE '' 
					END + 
					QIC.LB()
					,'DELEGATE'
			FROM @Delegate delegate
 
			INSERT INTO @Call (DelegateName,Call,ActionName)
			SELECT aspect.DelegateName, QIC.CallFactory(@ConfigName, @Token, @InterfaceId, aspect.AspectId, aspect.AspectReturnToken, aspect.TokenMap, CASE WHEN aspect.DelegateName IN ('DEFAULT') OR @HasDelegateName = 0 THEN 1 ELSE 2 END, '', aspect.CallFactory), aspect.ActionName
			FROM @Aspect aspect
			WHERE aspect.ActionName IN ('AFTER','AFTER ' + @TriggerAction)
			ORDER BY aspect.SortOrder	
 
			BEGIN
				SET @DelegateImplementation = ''
 
				SELECT @DelegateImplementation += Call + QIC.LB()
				FROM @Call
				WHERE DelegateName = '' and ActionName IN ('BEFORE','BEFORE ' + @TriggerAction)
				ORDER BY Id
 
				IF @DelegateImplementation <> '' SET @Implementation += @DelegateImplementation + QIC.LB()
			END
			
			BEGIN
				SET @DelegateImplementation = ''
 
				SELECT @DelegateImplementation += Call + QIC.LB()
				FROM @Call
				WHERE ActionName IN ('DELEGATE') and Call <> ''
				ORDER BY Id
 
				IF @DelegateImplementation <> '' SET @Implementation += @DelegateImplementation + QIC.LB()
			END
 
 
			BEGIN
				SET @DelegateImplementation = ''
 
				SELECT @DelegateImplementation += Call + QIC.LB()
				FROM @Call
				WHERE DelegateName = '' and ActionName IN ('AFTER','AFTER ' + @TriggerAction)
				ORDER BY Id
 
				IF @DelegateImplementation <> '' SET @Implementation += @DelegateImplementation + QIC.LB()
			END
 
			SET @Retval += 'GO' + QIC.LB()
			SET @Retval += 'CREATE TRIGGER ' + @TriggerName + ' ON ' + @ObjectName + QIC.LB()
			SET @Retval += 'INSTEAD OF ' + @TriggerAction + ' ' + QIC.LB()
			SET @Retval += 'AS' + QIC.LB()
			SET @Retval += 'BEGIN' + QIC.LB()
			SET @Retval += 'SET NOCOUNT ON' + QIC.LB()
			IF @Declare <> ''
			BEGIN
				SET @Retval += @Declare + QIC.LB()
			END
			SET @Retval += ISNULL(@Implementation + QIC.LB(),'')		
			SET @Retval += QIC.Indent(1)+ 'RETURN' + QIC.LB()
			SET @Retval += 'END' + QIC.LB()
 
 
		END
 
		CLOSE triggerCursor
		DEALLOCATE triggerCursor
 
	END
 
	RETURN @Retval
 
END
